package io.github.junxworks.qt.config.ds;

import java.io.IOException;
import java.sql.SQLException;

import javax.sql.DataSource;

import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.shardingsphere.driver.api.yaml.YamlShardingSphereDataSourceFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import io.github.junxworks.junx.core.util.ByteUtils;

@Configuration
@MapperScan(basePackages = { "io.github.junxworks.qt.*"}, annotationClass = Sharding.class, sqlSessionTemplateRef = "shardingSqlSessionTemplate")
public class ShardingDataSourceConfig {

	@Value("${spring.profiles.active:dev}")
	private String profile;

	@Bean
	@Primary
	public DataSource shardingDataSource() throws SQLException, IOException {
		ClassPathResource cpr = new ClassPathResource("/sharding-jdbc-" + profile + ".yml");
		return YamlShardingSphereDataSourceFactory.createDataSource(ByteUtils.inputStreamToBytes(cpr.getInputStream()));
	}

	@Primary
	@Bean(name = "shardingSqlSessionFactory")
	public SqlSessionFactory shardingSqlSessionFactory(@Qualifier("shardingDataSource") DataSource dataSource) throws Exception {
		SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
		bean.setDataSource(dataSource);
		SqlSessionFactory factory = bean.getObject();
		org.apache.ibatis.session.Configuration config = factory.getConfiguration();
		config.setMapUnderscoreToCamelCase(true);
		config.setLazyLoadingEnabled(true);
		config.setDefaultStatementTimeout(300);
		return factory;
	}

	@Primary
	@Bean(name = "shardingTransactionManager")
	public DataSourceTransactionManager shardingTransactionManager(@Qualifier("shardingDataSource") DataSource dataSource) {
		return new DataSourceTransactionManager(dataSource);
	}

	@Primary
	@Bean(name = "shardingSqlSessionTemplate")
	public SqlSessionTemplate shardingSqlSessionTemplate(@Qualifier("shardingSqlSessionFactory") SqlSessionFactory sqlSessionFactory) throws Exception {
		return new SqlSessionTemplate(sqlSessionFactory);
	}
	
}
